//
//  ZDataPrivate.h
//  Part of Z-Way.C library
//
//  Created by Alex Skalozub on 1/9/12.
//  Based on Z-Way source code written by Christian Paetz and Poltorak Serguei
//
//  Copyright (c) 2012 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zdata_private_h
#define zdata_private_h

#include "ZPlatform.h"
#include "ZErrors.h"
#include "ZData.h"
#include "ZDataList.h"
#include "ZDataDefs.h"
#include "ZLog.h"
#include "ZByteOperationsPrivate.h"

// By default they always use
#define ZWAY_ZDATA_STATIC_NAMES

typedef struct _ZDataStaticNamesInfo_s
{
    ZWCSTR name;
    _zhash_murmur_t hash;
} _ZDataStaticNamesInfo_t;

typedef struct _ZDataStaticNames_s
{
    size_t count;
    _ZDataStaticNamesInfo_t info[];
} _ZDataStaticNames_t;

struct _ZDataRootObject
{
    volatile ZWTHREAD data_thread;  // thread currently accessing data
    volatile uint32_t data_depth;   // current reentrancy depth
    ZWMUTEX data_mutex;             // data access sync mutex
    ZWMUTEXATTR data_mutex_attr;    // data access sync mutex attrs (for reentrancy)
    ZWLog log;
    ZWSTR name;
#if defined(ZWAY_ZDATA_STATIC_NAMES)
    const _ZDataStaticNames_t *static_names;
#endif
};

typedef union ZDataValueUnion_u
{
    ZWBOOL boolean_value;
    int integer_value;
    float float_value;
    ZWSTR string_value;
    ZWCSTR string_const_value;
    ZWBYTE *binary_value;
    int *integer_array;
    float *float_array;
    ZWSTR *string_array;
    void *ptr; // used only to copy the value without a cast
} ZDataValueUnion_t;

struct _ZDataValue
{
    ZDataValueUnion_t list_of_values;
    unsigned int count:27;
    ZWDataType type:4;
    ZWBOOL allocated:1;
};

typedef ZWBYTE ZDataFlags;
typedef struct _ZDataValue ZDataValue;

#define DATAHOLDER_FLAG_HIDDEN                   0x01 // Don't list among children
#define DATAHOLDER_FLAG_NOT_PERSISTED            0x02 // Don't save to cold storage (zddx/xxxxxxxx-DevicesData.xml)
#define DATAHOLDER_FLAG_NOT_INVALIDATED_CHILD    0x04 // Don't propogate to children on invalidation
#define DATAHOLDER_FLAG_LARGE                    0x08 // FOR FUTURE USE
#define DATAHOLDER_FLAG_PRIVATE                  0x10 // For Z-Way interval use. Don't call callback. No logging even in debug mode
#define DATAHOLDER_FLAG_READONLY                 0x20 // Immutable
#define DATAHOLDER_FLAG_NO_LOG                   0x40 // No logging even in debug mode

struct _ZDataHolder 
{
    union
    {
        ZWSTR name;
    #ifdef ZWAY_ZDATA_STATIC_NAMES
        _zhash_murmur_t static_name_id;
    #endif
        ZWCHAR flat_name_str[sizeof(char *)];
    };
    union
    {
        ZDataHolder parent;
        ZDataRootObject root;
    };
    ZDataHolder first_child;
    ZDataHolder next_sibling;
    ZDataCallbackList callbacks;
    ZTIME_T update_time;
    #ifndef DATA_INVALIDATE_FLAG
    ZTIME_T invalidate_time;
    #endif
    ZDataValue value;
    ZDataFlags flags;
    ZWBOOL is_root:1;
    #ifdef DATA_INVALIDATE_FLAG
    ZWBOOL invalidated:1;
    #endif
    #ifdef ZWAY_ZDATA_STATIC_NAMES
    ZWBOOL static_name:1;
    #endif
    ZWBOOL flat_name:1;
};

static inline ZWBOOL _zdata_is_persistent(const ZDataHolder data)
{
    if ((data->flags & DATAHOLDER_FLAG_NOT_PERSISTED))
    {
        return FALSE;
    }
    return TRUE;
}

ZWEXPORT_PRIVATE void _zdata_root_init_ext(const ZDataRootObject root, const ZWLog log, const ZWCSTR name, const _ZDataStaticNames_t *const static_names);
static inline void _zdata_root_init(const ZDataRootObject root, const ZWLog log, const ZWCSTR name)
{
    return _zdata_root_init_ext(root, log, name, NULL);
}
ZWEXPORT_PRIVATE void _zdata_root_free(ZDataRootObject root);
static inline ZWLog _zdata_root_get_log(const ZDataRootObject root)
{
    return root->log;
}

// free allocated data
ZWEXPORT_PRIVATE void _zdata_free(ZDataHolder data);

static inline void _zdata_init_empty(ZDataValue *const data_value)
{
    data_value->type = Empty;
}
static inline void _zdata_init_boolean(ZDataValue *const data_value, const ZWBOOL value)
{
    data_value->type = Boolean;
    data_value->list_of_values.boolean_value = value;
}
static inline void _zdata_init_integer(ZDataValue *const data_value, const int value)
{
    data_value->type = Integer;
    data_value->list_of_values.integer_value = value;
}
static inline void _zdata_init_float(ZDataValue *const data_value, const float value)
{
    data_value->type = Float;
    data_value->list_of_values.float_value = value;
}
static inline void _zdata_init_binary_allocated(ZDataValue *const data_value, ZWBYTE *const value, const size_t count)
{
    data_value->type = Binary;
    data_value->list_of_values.binary_value = value;
    data_value->count = count;
    data_value->allocated = TRUE;
}
static inline void _zdata_init_integer_array_allocated(ZDataValue *const data_value, int *const value, const size_t count)
{
    data_value->type = ArrayOfInteger;
    data_value->list_of_values.integer_array = value;
    data_value->count = count;
    data_value->allocated = TRUE;
}
static inline void _zdata_init_float_array_allocated(ZDataValue *const data_value, float *const value, const size_t count)
{
    data_value->type = ArrayOfFloat;
    data_value->list_of_values.float_array = value;
    data_value->count = count;
    data_value->allocated = TRUE;
}
static inline void _zdata_init_string_allocated_n(ZDataValue *const data_value, const ZWSTR value, const size_t count)
{
    data_value->type = String;
    data_value->list_of_values.string_value = value;
    data_value->count = count + 1;
    data_value->allocated = TRUE;
}
static inline void _zdata_init_string_allocated(ZDataValue *const data_value, const ZWSTR value)
{
    _zdata_init_string_allocated_n(data_value, value, str_length(value));
}
static inline void _zdata_init_string_array_allocated(ZDataValue *const data_value, ZWSTR *const value, const size_t count)
{
    data_value->type = ArrayOfString;
    data_value->list_of_values.string_array = value;
    data_value->count = count;
    data_value->allocated = TRUE;
}

static inline void _zdata_init_ptr_null(ZDataValue *const data_value, const ZWDataType type)
{
    data_value->type = type;
    data_value->list_of_values.ptr = NULL;
    data_value->count = 0;
    data_value->allocated = FALSE;
}

static inline void _zdata_init_ptr_allocated(ZDataValue *const data_value, const ZWDataType type, void *const ptr, const size_t count)
{
    data_value->type = type;
    data_value->list_of_values.ptr = ptr;
    data_value->count = count;
    data_value->allocated = TRUE;
}

// free value
ZWEXPORT_PRIVATE void _zdata_free_value(ZDataValue *const data_value);

ZWEXPORT_PRIVATE void _zdata_remove_children(ZDataHolder data);

ZWEXPORT_PRIVATE ZWError _zdata_detached_copy(const ZDataHolder src, ZDataHolder *const dst);

// creates a new child DataHolder object with specified name
// returns NULL if validation or allocation failed
ZWEXPORT_PRIVATE ZDataHolder _zdata_create(ZDataHolder parent, const char *name);
ZWEXPORT_PRIVATE ZWError _zdata_create_and_set_flags(const ZDataHolder parent, const ZWCSTR name, const ZDataFlags flags);
ZWEXPORT_PRIVATE ZWError _zdata_create_boolean_and_set_flags(const ZDataHolder parent, const ZWCSTR name, const ZWBOOL val, const ZDataFlags flags);
ZWEXPORT_PRIVATE ZWError _zdata_create_boolean(const ZDataHolder parent, const ZWCSTR name, const ZWBOOL val);
ZWEXPORT_PRIVATE ZWError _zdata_create_integer_and_set_flags(const ZDataHolder parent, const ZWCSTR name, const int val, const ZDataFlags flags);
ZWEXPORT_PRIVATE ZWError _zdata_create_integer(const ZDataHolder parent, const ZWCSTR name, const int val);
ZWEXPORT_PRIVATE ZWError _zdata_create_string_allocated(const ZDataHolder parent, const ZWCSTR name, const ZWSTR value); // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
ZWEXPORT_PRIVATE ZDataHolder _zdata_create_numeric_word_child(const ZDataHolder parent, const ZWWORD childId);
static inline ZDataHolder _zdata_create_numeric_byte_child(const ZDataHolder parent, const ZWBYTE childId)
{
    return _zdata_create_numeric_word_child(parent, (ZWWORD)childId);
};
ZWEXPORT_PRIVATE ZDataHolder _zdata_create_root(const ZDataRootObject root, const char *name);

ZWEXPORT_PRIVATE ZDataRootObject _zdata_get_root(const ZDataHolder data);

// removes a specified DataHolder
ZWEXPORT_PRIVATE void _zdata_delete(ZDataHolder data);

// finds a child DataHolder with specified path
ZWEXPORT_PRIVATE ZDataHolder _zdata_find(const ZDataHolder data, const ZWCSTR path);
ZWEXPORT_PRIVATE ZDataHolder _zdata_find_numeric_word_child(const ZDataHolder parent, const ZWWORD childId);
static inline ZDataHolder _zdata_find_numeric_byte_child(const ZDataHolder parent, const ZWBYTE childId)
{
    return _zdata_find_numeric_word_child(parent, (ZWWORD)childId);
};
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_integer(const ZDataHolder data, const ZWCSTR path, const int value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_integer_read_only(const ZDataHolder data, const ZWCSTR path, const int value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_float(const ZDataHolder data, const ZWCSTR path, const float value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_boolean(const ZDataHolder data, const ZWCSTR path, const ZWBOOL value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_boolean_read_only(const ZDataHolder data, const ZWCSTR path, const ZWBOOL value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_empty(const ZDataHolder data, const ZWCSTR path);

ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_binary_allocated(const ZDataHolder data, const ZWCSTR path, ZWBYTE *const value, const size_t count); // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_binary_copy(const ZDataHolder data, const ZWCSTR path, const ZWBYTE *const value, const size_t count);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_binary_copy_read_only(const ZDataHolder data, const ZWCSTR path, const ZWBYTE *const value, const size_t count);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_binary_static(const ZDataHolder data, const ZWCSTR path, const ZWBYTE *const value, const size_t count);
static inline ZWError _zdata_find_and_set_binary_null(const ZDataHolder data, const ZWCSTR path)
{
    return _zdata_find_and_set_binary_copy(data, path, NULL, 0);
};

ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_integer_array_allocated(const ZDataHolder data, const ZWCSTR path, int *const value, const size_t count); // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_integer_array_copy(const ZDataHolder data, const ZWCSTR path, const int *const value, const size_t count);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_integer_array_static(const ZDataHolder data, const ZWCSTR path, const int *const value, const size_t count);
static inline ZWError _zdata_find_and_set_integer_array_null(const ZDataHolder data, const ZWCSTR path)
{
    return _zdata_find_and_set_integer_array_copy(data, path, NULL, 0);
};

ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_string_allocated(const ZDataHolder data, const ZWCSTR path, const ZWSTR value); // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_string_copy(const ZDataHolder data, const ZWCSTR path, const ZWCSTR value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_string_copy_read_only(const ZDataHolder data, const ZWCSTR path, const ZWCSTR value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_string_copy_n(const ZDataHolder data, const ZWCSTR path, const ZWCSTR value, const size_t n);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_string_static(const ZDataHolder data, const ZWCSTR path, const ZWCSTR value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_set_string_fmt(const ZDataHolder data, const ZWCSTR path, ZWCSTR format, ...) __printflike(3, 4);
static inline ZWError _zdata_find_and_set_string_null(const ZDataHolder data, const ZWCSTR path)
{
    return _zdata_find_and_set_string_copy(data, path, NULL);
};

ZWEXPORT_PRIVATE int _zdata_find_and_get_integer(const ZDataHolder data, const ZWCSTR path, const int default_value);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_get_binary(const ZDataHolder data, const ZWCSTR path, const ZWBYTE **const value, size_t *const count);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_get_integer_array(const ZDataHolder data, const ZWCSTR path, const int **const value, size_t *const count);
ZWEXPORT_PRIVATE ZWBOOL _zdata_find_and_get_boolean(const ZDataHolder data, const ZWCSTR path, const ZWBOOL default_value);
ZWEXPORT_PRIVATE ZWCSTR _zdata_find_and_get_string(const ZDataHolder data, const ZWCSTR path, const ZWCSTR default_value);
ZWEXPORT_PRIVATE ZWBOOL _zdata_find_and_is_empty(const ZDataHolder data, const ZWCSTR path);
ZWEXPORT_PRIVATE ZDataHolder _zdata_find_or_create(const ZDataHolder parent, const ZWCSTR name);
ZWEXPORT_PRIVATE ZDataHolder _zdata_find_or_create_numeric_word_child(const ZDataHolder parent, const ZWWORD childId);
static inline ZDataHolder _zdata_find_or_create_numeric_byte_child(const ZDataHolder parent, const ZWBYTE childId)
{
    return _zdata_find_or_create_numeric_word_child(parent, (ZWWORD)childId);
};
ZWEXPORT_PRIVATE ZWError _zdata_find_or_create_set_integer(const ZDataHolder parent, const ZWCSTR name, const int value);
ZWEXPORT_PRIVATE ZWError _zdata_find_or_create_set_boolean(const ZDataHolder parent, const ZWCSTR name, const ZWBOOL value);

ZWEXPORT_PRIVATE void _zdata_update_now(ZDataHolder data);

// remove value and all children
ZWEXPORT_PRIVATE void _zdata_clear(ZDataHolder data);

ZWEXPORT_PRIVATE ZWBOOL _zdata_get_boolean(const ZDataHolder data, ZWBOOL default_value);
ZWEXPORT_PRIVATE int _zdata_get_integer(const ZDataHolder data, int default_value);
ZWEXPORT_PRIVATE float _zdata_get_float(const ZDataHolder data, float default_value);
ZWEXPORT_PRIVATE ZWCSTR _zdata_get_string(const ZDataHolder data, ZWCSTR default_value);

ZWEXPORT_PRIVATE ZWBOOL _zdata_name_is_alloc(const ZDataHolder data);
ZWEXPORT_PRIVATE ZWCSTR _zdata_get_name(const ZDataHolder data);

ZWEXPORT_PRIVATE ZWError _zdata_set_update_time(const ZDataHolder data, time_t time);
ZWEXPORT_PRIVATE ZDataIterator _zdata_first_child(const ZDataHolder data);
ZWEXPORT_PRIVATE ZDataIterator _zdata_next_child(ZDataIterator child);

static inline ZWDataType _zdata_get_type(const ZDataHolder data)
{
    return data->value.type;
};

static inline void _zdata_set_flags_unsafe(const ZDataHolder data, const ZDataFlags flags)
{
    data->flags = flags;
};

/**
 * @brief
 * Returns the dataholder id if it is set otherwise ZDATA_STATIC_NAME_INVALID_VALUE
 *
 * @param[in] data
 * A pointer to a valid dataholder
 *
 * @return _zhash_murmur_t
 */
ZWEXPORT_PRIVATE _zhash_murmur_t _zdata_get_name_id(const ZDataHolder data);

typedef enum ZDataMassCreateEntryType_e
{
    ZDataMassCreateEntryType_EntryLeaf,
    ZDataMassCreateEntryType_EntrySubtreeEnter,
    ZDataMassCreateEntryType_EntrySubtreeLeave,
    ZDataMassCreateEntryType_EntryEof,
} ZDataMassCreateEntryType_t;

typedef struct ZDataMassCreate_s
{
    ZWCSTR name;
    ZDataValueUnion_t list_of_values;
    // Should be totally 32 bits to be aligned
    ZWWORD count : 13; // Size of array value
    ZDataMassCreateEntryType_t entryType : 2;
    ZDataFlags flags : 8;
    ZWDataType type : 8;
    ZWBOOL static_const : 1;
} ZDataMassCreate_t;

#define ZDATA_DH_EOF() \
    { \
        .name = NULL, \
        .list_of_values = {.integer_value = 0}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryEof, \
        .flags = 0, \
        .type = Empty, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_SUB_START_EMPTY(NAME, FLAGS) \
    { \
        .name = NAME, \
        .list_of_values = {.integer_value = 0}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntrySubtreeEnter, \
        .flags = FLAGS, \
        .type = Empty, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_SUB_START_INTEGER(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.integer_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntrySubtreeEnter, \
        .flags = FLAGS, \
        .type = Integer, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_SUB_START_BOOLEAN(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.boolean_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntrySubtreeEnter, \
        .flags = FLAGS, \
        .type = Boolean, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_SUB_END() \
    { \
        .name = NULL, \
        .list_of_values = {.integer_value = 0}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntrySubtreeLeave, \
        .flags = 0, \
        .type = Empty, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_EMPTY(NAME, FLAGS) \
    { \
        .name = NAME, \
        .list_of_values = {.integer_value = 0}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = Empty, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_BOOLEAN(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.boolean_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = Boolean, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_INTEGER(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.integer_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = Integer, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_FLOAT(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.float_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = Float, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_STRING(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.string_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = String, \
        .static_const = FALSE, \
    }

#define ZDATA_DH_STRING_STATIC(NAME, FLAGS, VALUE) \
    { \
        .name = NAME, \
        .list_of_values = {.string_const_value = VALUE}, \
        .count = 0, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = String, \
        .static_const = TRUE, \
    }

#define ZDATA_DH_BINARY(NAME, FLAGS, VALUE, COUNT) \
    { \
        .name = NAME, \
        .list_of_values = {.binary_value = VALUE}, \
        .count = COUNT, \
        .entryType = ZDataMassCreateEntryType_EntryLeaf, \
        .flags = FLAGS, \
        .type = Binary, \
        .static_const = FALSE, \
    }

ZWEXPORT_PRIVATE ZWError _zdata_mass_create(ZDataHolder parent, const ZDataMassCreate_t *data);

ZWEXPORT_PRIVATE ZWError _zdata_mass_create_and_invalidate(const ZDataHolder parent, const ZWCSTR *const p_name, const size_t count);
ZWEXPORT_PRIVATE ZWError _zdata_mass_invalidate(const ZDataHolder parent, const ZWCSTR *const p_name, const size_t count);
ZWEXPORT_PRIVATE ZWError _zdata_mass_invalidate_tree(const ZDataHolder parent, const ZWCSTR *const p_name, const size_t count);
ZWEXPORT_PRIVATE ZWError _zdata_find_and_invalidate(const ZDataHolder parent, const ZWCSTR name);
ZWEXPORT_PRIVATE ZWError _zdata_find_invalidate_tree(const ZDataHolder parent, const ZWCSTR name);

typedef enum _ZDataAction_e
{
    _ZDataActionStatic,
    _ZDataActionCopy,
    _ZDataActionAllocated,
    _ZDataActionOld, // Old behaviour, not to be used in new code. Like Static, but will lead to leaks if allocated memory is passed by the user
} _ZDataAction_t;

ZWEXPORT_PRIVATE ZWError _zdata_set_empty(const ZDataHolder data);
ZWEXPORT_PRIVATE ZWError _zdata_set_boolean(const ZDataHolder data, const ZWBOOL value);
ZWEXPORT_PRIVATE ZWError _zdata_set_integer(const ZDataHolder data, const int value);
ZWEXPORT_PRIVATE ZWError _zdata_set_float(const ZDataHolder data, const float value);

ZWEXPORT_PRIVATE ZWError _zdata_set_binary(const ZDataHolder data, ZWBYTE *const value, const size_t count, const _ZDataAction_t action);
static inline ZWError _zdata_set_binary_allocated(const ZDataHolder data, ZWBYTE *const value, const size_t count) // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
{
    return _zdata_set_binary(data, value, count, _ZDataActionAllocated);
};
static inline ZWError _zdata_set_binary_copy(const ZDataHolder data, const ZWBYTE *const value, const size_t count)
{
    return _zdata_set_binary(data, (ZWBYTE *)value, count, _ZDataActionCopy);
};
static inline ZWError _zdata_set_binary_static(const ZDataHolder data, const ZWBYTE *const value, const size_t count)
{
    return _zdata_set_binary(data, (ZWBYTE *)value, count, _ZDataActionStatic);
};
static inline ZWError _zdata_set_binary_null(const ZDataHolder data)
{
    return _zdata_set_binary_copy(data, NULL, 0);
};

ZWEXPORT_PRIVATE ZWError _zdata_set_integer_array(const ZDataHolder data, int *const value, const size_t count, const _ZDataAction_t action);
static inline ZWError _zdata_set_integer_array_allocated(const ZDataHolder data, int *const value, const size_t count) // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
{
    return _zdata_set_integer_array(data, value, count, _ZDataActionAllocated);
};
static inline ZWError _zdata_set_integer_array_copy(const ZDataHolder data, const int *const value, const size_t count)
{
    return _zdata_set_integer_array(data, (int *)value, count, _ZDataActionCopy);
};
static inline ZWError _zdata_set_integer_array_static(const ZDataHolder data, const int *const value, const size_t count)
{
    return _zdata_set_integer_array(data, (int *)value, count, _ZDataActionStatic);
};
static inline ZWError _zdata_set_integer_array_null(const ZDataHolder data)
{
    return _zdata_set_integer_array_copy(data, NULL, 0);
};

ZWEXPORT_PRIVATE ZWError _zdata_set_float_array(const ZDataHolder data, float *const value, const size_t count, const _ZDataAction_t action);
static inline ZWError _zdata_set_float_array_allocated(const ZDataHolder data, float *const value, const size_t count) // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
{
    return _zdata_set_float_array(data, value, count, _ZDataActionAllocated);
};
static inline ZWError _zdata_set_float_array_copy(const ZDataHolder data, const float *const value, const size_t count)
{
    return _zdata_set_float_array(data, (float *)value, count, _ZDataActionCopy);
};
static inline ZWError _zdata_set_float_array_static(const ZDataHolder data, const float *const value, const size_t count)
{
    return _zdata_set_float_array(data, (float *)value, count, _ZDataActionStatic);
};
static inline ZWError _zdata_set_float_array_null(const ZDataHolder data)
{
    return _zdata_set_float_array_copy(data, NULL, 0);
};

ZWEXPORT_PRIVATE ZWError _zdata_set_string(const ZDataHolder data, const ZWSTR value, const _ZDataAction_t action);
static inline ZWError _zdata_set_string_allocated(const ZDataHolder data, const ZWSTR value) // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
{
    return _zdata_set_string(data, value, _ZDataActionAllocated);
};
static inline ZWError _zdata_set_string_copy(const ZDataHolder data, const ZWCSTR value)
{
    return _zdata_set_string(data, (ZWSTR)value, _ZDataActionCopy);
};
static inline ZWError _zdata_set_string_static(const ZDataHolder data, const ZWCSTR value)
{
    return _zdata_set_string(data, (ZWSTR)value, _ZDataActionStatic);
};
static inline ZWError _zdata_set_string_null(const ZDataHolder data)
{
    return _zdata_set_string_static(data, NULL);
};
ZWEXPORT_PRIVATE ZWError _zdata_set_string_copy_n(const ZDataHolder data, const ZWCSTR value, const size_t n);
ZWEXPORT_PRIVATE ZWError _zdata_set_string_fmt(ZDataHolder data, PRINTF_FORMAT_STRING ZWCSTR format, ...) __printflike(2, 3);

ZWEXPORT_PRIVATE ZWError _zdata_set_string_array(ZDataHolder data, ZWSTR *value, size_t count, const _ZDataAction_t action);
static inline ZWError _zdata_set_string_array_allocated(ZDataHolder data, ZWSTR *const value, const size_t count) // This function can free the value in some cases, so the caller MUST NOT use it after giving to this function
{
    return _zdata_set_string_array(data, (ZWSTR *)value, count, _ZDataActionAllocated);
};
static inline ZWError _zdata_set_string_array_copy(ZDataHolder data, ZWCSTR *const value, const size_t count)
{
    return _zdata_set_string_array(data, (ZWSTR *)value, count, _ZDataActionCopy);
};
static inline ZWError _zdata_set_string_array_static(ZDataHolder data, ZWCSTR *const value, const size_t count)
{
    return _zdata_set_string_array(data, (ZWSTR *)value, count, _ZDataActionStatic);
};
static inline ZWError _zdata_set_string_array_null(ZDataHolder data)
{
    return _zdata_set_string_array_static(data, NULL, 0);
};

ZWEXPORT_PRIVATE ZWError _zdata_set(const ZDataHolder data, ZDataValue *const data_value);

#endif
